package com.xyzwps.server.paimon.model.repository

import com.xyzwps.server.paimon.model.entity.User
import com.xyzwps.server.paimon.model.table.UserTable
import com.xyzwps.server.paimon.value.Phone
import com.xyzwps.server.paimon.value.UserId
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.update
import org.springframework.stereotype.Repository

internal val u = UserTable

internal fun rowToUser(it: ResultRow): User =
    User(
        id = UserId(it[u.id].value),
        nickname = it[u.nickname],
        phone = Phone(it[u.phone]),
        createdAt = it[u.createdAt]
    )

@Repository
class UserRepository {

    fun save(user: User): User {
        if (user.id == null) {
            val id = UserTable.insertAndGetId {
                it[nickname] = user.nickname
                it[phone] = user.phone.value
                it[createdAt] = user.createdAt
            }
            return user.copy(id = UserId(id.value))
        }

        UserTable.update({ u.id eq user.id.value }) {
            it[nickname] = user.nickname
            it[phone] = user.phone.value
            it[createdAt] = user.createdAt
        }
        return user

    }

    fun findById(id: UserId): User? =
        UserTable.selectAll()
            .where { u.id eq id.value }
            .map(::rowToUser)
            .firstOrNull()

    fun findAllById(ids: List<UserId>): List<User> = if (ids.isEmpty()) emptyList() else
        UserTable.selectAll()
            .where { u.id inList ids.map { it.value } }
            .map(::rowToUser)

    fun findByPhone(phone: Phone): User? =
        UserTable.selectAll()
            .where { u.phone eq phone.value }
            .map(::rowToUser)
            .firstOrNull()

    fun existsByPhone(phone: String): Boolean =
        !UserTable.selectAll()
            .where { u.phone eq phone }
            .empty()
}
